<?php
namespace app\apijson\query;

use app\apijson\core\ApiJsonException;

/**
 * QueryBuilder
 *
 * 统一入口，负责分发 APIJSON 解析后的结构到不同的处理器：
 * - TableQuery 处理单表/多表（type=table）查询
 * - ArrayQuery 处理 [] 结构和分页递归
 * - PathAssigner 处理 total@/num@/info@ 路径赋值和重命名
 *
 * 只需调用 build($parsed) 即可获得最终结果。
 */
class QueryBuilder
{
    /**
     * @var TableQuery 处理 type=table 的 key
     */
    public $tableQuery;
    /**
     * @var ArrayQuery 处理 [] 结构
     */
    public $arrayQuery;
    /**
     * @var PathAssigner 处理路径赋值和重命名
     */
    public $pathAssigner;

    public function __construct()
    {
        // 初始化各子处理器，传递自身用于递归
        $this->tableQuery = new TableQuery($this);
        $this->arrayQuery = new ArrayQuery($this);
        $this->pathAssigner = new PathAssigner();
    }

    /**
     * 递归构建 APIJSON 查询结果
     * @param array $parsed 由 Parser 解析后的结构化数组
     * @param string $method 操作类型 get/post/patch/delete
     * @return array        构建后的最终结果
     */
    public function build($parsed, $method = 'get')
    {
        $result = [];
        // 1. 分发每个 key 到对应处理器
        foreach ($parsed as $key => $value) {
            if (isset($value['type']) && $value['type'] === 'table') {
                // 根级模型直接查表，返回对象（只取第一条或空对象）
                if ($method === 'get') {
                    $data = $this->tableQuery->handle($key, $value);
                    $result[$key] = is_array($data) && count($data) > 0 ? $data[0] : (object)[];
                } elseif ($method === 'post') {
                    $result[$key] = $this->tableQuery->insert($key, $value);
                } elseif ($method === 'patch') {
                    $result[$key] = $this->tableQuery->update($key, $value);
                } elseif ($method === 'delete') {
                    $result[$key] = $this->tableQuery->delete($key, $value);
                } else {
                    throw new ApiJsonException('不支持的操作类型: ' . $method);
                }
            } elseif ($key === '[]') {
                // [] 结构交给 ArrayQuery，结果直接合并到顶层，避免多包一层 []
                $arrResult = $this->arrayQuery->handle($value);
                foreach ($arrResult as $k => $v) {
                    $result[$k] = $v;
                }
            } else {
                // 其它参数直接保留
                $result[$key] = $value;
            }
        }
        // 2. 路径赋值和重命名交给 PathAssigner
        $result = $this->pathAssigner->assign($parsed, $result);
        return $result;
    }
} 